package top.codecrab.eblog.utils;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CannedAccessControlList;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.web.multipart.MultipartFile;
import top.codecrab.eblog.common.response.R;
import top.codecrab.eblog.config.Constants;
import top.codecrab.eblog.config.OssProperties;
import top.codecrab.eblog.shiro.AccountProfile;

import java.io.File;
import java.io.IOException;
import java.util.Date;

@Slf4j
public class UploadUtil {

    public final static String TYPE_AVATAR = "avatar";
    public final static String TYPE_POST = "post";

    public static R upload(String type, MultipartFile file) throws IOException {
        if (OssProperties.ACTIVE) {
            return uploadToOss(type, file);
        } else {
            return uploadToLocal(type, file);
        }
    }

    private static R uploadToLocal(String type, MultipartFile file) {
        // 如果result为空表示通过校验
        R r = checkImageSize(type, file);
        if (r != null) return r;

        // 获取文件名
        String fileName = file.getOriginalFilename();
        if (StrUtil.isBlank(fileName)) {
            fileName = IdUtil.fastSimpleUUID();
        }
        log.info("上传的文件名为：" + fileName);
        // 获取文件的后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        log.info("上传的后缀名为：" + suffixName);
        // 文件上传后的路径
        String filePath = Constants.UPLOAD_DIR;

        AccountProfile profile = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        if ("avatar".equalsIgnoreCase(type)) {
            fileName = "/avatar/avatar_" + profile.getId() + suffixName;

        } else if ("post".equalsIgnoreCase(type)) {
            fileName = "/post/" + profile.getId() + "/post_" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN) + suffixName;
        }

        File dest = new File(filePath + fileName);
        // 检测是否存在目录
        if (!dest.getParentFile().exists()) {
            if (dest.getParentFile().mkdirs()) {
                log.info("创建目标父目录");
            }
        }
        try {
            file.transferTo(dest);
            log.info("上传成功后的文件路径未：" + filePath + fileName);

            String path = filePath + fileName;
            String url = "/upload" + fileName;

            log.info("url ---> {}", url);
            log.info("path ---> {}", path);
            return R.ok(url);
        } catch (IllegalStateException | IOException e) {
            e.printStackTrace();
        }
        return R.ok(null);
    }

    private static R uploadToOss(String type, MultipartFile file) throws IOException {
        // 如果result为空表示通过校验
        R r = checkImageSize(type, file);
        if (r != null) return r;

        String fileName = file.getOriginalFilename();

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(
            OssProperties.ENDPOINT,
            OssProperties.KEY_ID,
            OssProperties.KEY_SECRET
        );

        // 判断桶是否存在
        if (!ossClient.doesBucketExist(OssProperties.BUCKET_NAME)) {
            // 不存在则创建桶
            ossClient.createBucket(OssProperties.BUCKET_NAME);
            // 授权
            ossClient.setBucketAcl(OssProperties.BUCKET_NAME, CannedAccessControlList.PublicRead);
        }

        // 组装文件路径  avatar/2021/04/26/fileName.jpg
        String filePath = type +
            DateUtil.format(new Date(), "/yyyy/MM/dd/") +
            IdUtil.fastSimpleUUID() + "." +
            FileUtil.getSuffix(fileName);

        // 填写Bucket名称和Object完整路径。Object完整路径中不能包含Bucket名称。
        ossClient.putObject(OssProperties.BUCKET_NAME, filePath, file.getInputStream());
        // 关闭OSSClient。
        ossClient.shutdown();
        // 阿里云文件绝对路径
        String url = StrUtil.format("https://{}.{}/{}", OssProperties.BUCKET_NAME, OssProperties.ENDPOINT, filePath);
        return R.ok(url);
    }

    private static R checkImageSize(String type, MultipartFile file) {
        if (StrUtil.isBlank(type) || file.isEmpty()) {
            return R.fail("上传失败");
        }

        if ("avatar".equalsIgnoreCase(type) && file.getSize() > 500 * 1024) {
            return R.fail("图片大小超出限制");
        }

        if ("post".equalsIgnoreCase(type) && file.getSize() > 5000 * 1024) {
            return R.fail("图片大小超出限制");
        }
        return null;
    }
}
